package com.linrung.gdsfrz.electronicseal.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.linrung.core.model.ResultData;
import com.linrung.core.utils.StringTools;
import com.linrung.gdsfrz.RequestApiUtils;
import com.linrung.gdsfrz.electronicseal.GDESealAPI;
import com.linrung.gdsfrz.electronicseal.GDSElectronicSealAPI;
import com.linrung.gdsfrz.electronicseal.IElectronicSealAPIService;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.HashMap;
import java.util.Map;

/**
 * 电子签章API实现类
 * @author wurenlong
 */
@Service("electronicSealAPIService")
@Transactional(propagation=Propagation.REQUIRED, transactionManager="transactionManager")
public class ElectronicSealAPIServiceImpl implements IElectronicSealAPIService {

    private static final Logger logger = Logger.getLogger(ElectronicSealAPIServiceImpl.class);

    /** 模块服务名称 **/
    private static final String MODEL_SERVICE_NAME = "电子签章API";

    /** headers里的 x-tif-uuid是用户唯一标识 **/
    private static final String HEADERS_X_TIF_UUID = "x-tif-uuid";

    /**
     * <h1>文件上传(云)</h1>
     * @param pdfFile
     * @return ResultData<Object>
     * @throws FileNotFoundException
     */
    @Override
    public ResultData<JSONObject> uploadSignedFile(File pdfFile, String fileName, String userId) throws FileNotFoundException {
        if(null == pdfFile || !pdfFile.exists() || pdfFile.length() == 0) {
            throw new FileNotFoundException("上传文件不存在");
        }
        ResultData<JSONObject> rd = ResultData.FAILURE();
        try {
            JSONObject respJson = GDESealAPI.FILE_UPLOAD.upload(userId, fileName, pdfFile);
            rd = ResultData.SUCCESS();
            rd.setData(respJson);
        } catch (Exception e) {
            logger.error(String.format("%s:上传待签章文件(用户标识)", MODEL_SERVICE_NAME), e);
            rd.setDesc("出现异常:".concat(e.getMessage()));
        }
        return rd;
    }

    /**
     * <h1>文件上传(云)</h1>
     * @param realPath 项目绝对路径
     * @param filePath 文件相对路径
     * @return ResultData<Object>
     */
    @Override
    public ResultData<JSONObject> uploadSignedFile(String realPath, String filePath, String fileName, String userId) throws FileNotFoundException {
        String localPath = realPath.concat(filePath);
        File pdfFile = new File(localPath);
        if(!pdfFile.exists() || pdfFile.length() == 0) {
            throw new FileNotFoundException("上传文件不存在");
        }
        return uploadSignedFile(pdfFile, fileName, userId);
    }

    /**
     * <h1>获取印章信息（用户标识）</h1>
     * @param userId 用户ID
     * @return ResultData<Object>
     */
    @Override
    public ResultData<JSONArray> listImageByUserId(String userId) {
        ResultData<JSONArray> rs = ResultData.FAILURE();
        if(StringTools.isBlank(userId)) {
            rs.setDesc("关键参数不能为空");
            return rs;
        }
        try {
            Map<String, String> headerMap = new HashMap<String, String>();
            headerMap.put(HEADERS_X_TIF_UUID, userId);
            JSONObject responseJson = RequestApiUtils.commonPost(GDSElectronicSealAPI.GDATA_SEAL_PERSON_GETIMAGEBYUUID, null, RequestApiUtils.API_TYPE_E_SEAL, headerMap);
            if(responseJson.getInt("errcode") == 0) {
                rs = ResultData.SUCCESS();
                rs.setData(responseJson.getJSONArray("dataSeal"));
            } else {
                rs.setDesc(responseJson.getString("errmsg"));
            }
        } catch (Exception e) {
            logger.error(String.format("%s:获取印章信息(用户标识)", MODEL_SERVICE_NAME), e);
            rs.setDesc("出现异常:".concat(e.getMessage()));
        }
        return rs;
    }

    /**
     * <h1>已签章文件下载</h1>
     * @param siteId 网站ID由电子印章厂家提供
     * @param fileId 已签章文件唯一标识
     * @param realPath 存储文件根目录绝对路径
     * @param savePath 存储文件相对路径
     * @return ResultData<Object>
     */
    @Override
    public ResultData<Object> downloadSignedFileByFileId(String siteId, String fileId, String realPath, String savePath) {
        ResultData<Object> rs = ResultData.FAILURE();
        if(StringTools.isBlank(fileId) || StringTools.isBlank(siteId)) {
            rs.setDesc("关键参数不能为空");
            return rs;
        }
        try {
            return GDESealAPI.FILE_DOWNLOAD.download(fileId, realPath, savePath);
        } catch (Exception e) {
            logger.error(String.format("%s:下载签章文件", MODEL_SERVICE_NAME), e);
            rs.setDesc("出现异常:".concat(e.getMessage()));
        }
        return rs;
    }

    /**
     * 按文件编号验签
     * @param documentId 已签署的文件编号
     * @return ResultData
     */
    @Override
    public ResultData<JSONArray> verifyByDocumentId(String documentId, String userId) {
        ResultData<JSONArray> rs = ResultData.FAILURE();
        if(StringTools.isBlank(documentId)) {
            rs.setDesc("关键参数不能为空");
            return rs;
        }
        try {
            Map<String, String> headerMap = new HashMap<String, String>();
            headerMap.put(HEADERS_X_TIF_UUID, userId);
            JSONObject responseJson = RequestApiUtils.commonPost(GDSElectronicSealAPI.GDATA_PDF_VERIFY + "?documentId=" + documentId, null, RequestApiUtils.API_TYPE_E_SEAL, headerMap);
            if(responseJson.getInt("errcode") == 0 && responseJson.getInt("verifyResult") == 0) {
                rs = ResultData.SUCCESS();
                rs.setData(responseJson.getJSONArray("singInfo"));
            } else {
                rs.setDesc(responseJson.getString("errmsg"));
            }
        } catch (Exception e) {
            logger.error(String.format("%s:按文件编号验签", MODEL_SERVICE_NAME), e);
            rs.setDesc("出现异常:".concat(e.getMessage()));
        }
        return rs;
    }

    /**
     *  按关键字签章
     * @param documentName 文件名称
     * @param documentPath 文件系统地址的相对路径
     * @param siteId 分配各个业务系统的id
     * @param outUserId 用章人Id。
     * @param title 最长100 为文档设置的标题。对接业务系统可通过该参数为每个文档设置不同的标题，以便后续对文档进行检索。
     * @param signatoriesList 多个签章信息
*               page	int	√	文件页码，从1开始。
     *          keyWord	String	√	签章关键字字段：默认页面查找到第一个关键字
     *          sealId	String	√	该签署用户在签署时使用电子印章编号
     *          localType	int		关键字签署（0:从最后一页向前，1:从第一页向后）搜索所有的关键字： 2
     * @return ResultData
     */
    @Override
    public ResultData<JSONArray> dynamicSignByCode(String documentName, String documentPath, String siteId, String outUserId, String title, JSONArray signatoriesList) {
        ResultData<JSONArray> rs = ResultData.FAILURE();
        if (!StrUtil.isAllNotBlank(documentName, documentPath, siteId, outUserId, title)) {
            rs.setDesc("关键参数不能为空");
            return rs;
        }
        if (CollUtil.size(signatoriesList) == 0) {
            rs.setDesc("关键参数不能为空");
            return rs;
        }
        try {
            Map<String, String> headerMap = new HashMap<String, String>();
            headerMap.put(HEADERS_X_TIF_UUID, outUserId);
            Map<String, Object> params = new HashMap<>();
            params.put("timestamp", DateUtil.current());
            params.put("documentName", documentName);
            params.put("documentPath", documentPath);
            params.put("siteId", siteId);
            params.put("outUserId", outUserId);
            params.put("title", title);
            params.put("signatoriesList", signatoriesList);
            JSONObject responseJson = RequestApiUtils.commonPost(GDSElectronicSealAPI.CORE_DYNAMICSIGN+"?siteId=" + siteId, params, RequestApiUtils.API_TYPE_E_SEAL, headerMap);
            if(responseJson.getBoolean("success")) {
                rs = ResultData.SUCCESS();
                rs.setData(responseJson.getJSONArray("data"));
            } else {
                rs.setDesc(responseJson.getString("errorCode") + ":" + responseJson.getString("errorMsg"));
            }
        } catch (Exception e) {
            logger.error(String.format("%s:按关键字签章", MODEL_SERVICE_NAME), e);
            rs.setDesc("出现异常:".concat(e.getMessage()));
        }
        return rs;
    }
}
